<?php

namespace App\HttpController\Home\Theme\Inception;

use App\HttpController\Home\IndexInterface;
use Exception;
use EasySwoole\ORM\DbManager;
use EasySwoole\Template\Render;
use EasySwoole\EasySwoole\Task\TaskManager;

use App\Common\Tools;
use App\Common\RedisCache;
use App\Model\Article\ {
    Nav,
    Article,
    FriendLink,
};
use App\Task\ArticleRead as TaskArticleRead;

class Index implements IndexInterface
{
    /**
     * @description: 首页
     * @param {*}
     * @return {*}
     */
    public function index()
    {
        $assign  = $this->getPublic();
        $linkkey = 'link:home';
        $links = RedisCache::get($linkkey, function() {
            return DbManager::getInstance()->invoke(function ($client){
                $model = FriendLink::invoke($client);
                return $model->getLinks();
            });
        });

        $artNewkey = 'article:home';
        $articles['list'] = RedisCache::get($artNewkey, function() {
            return DbManager::getInstance()->invoke(function ($client){
                $model = Nav::invoke($client);
                return $model->getHomeNavArts();
            });
        });

        $artNewkey = 'article:home:news';
        $articles['news'] = RedisCache::get($artNewkey, function() {
            return DbManager::getInstance()->invoke(function ($client){
                $model = Article::invoke($client);
                return $model->getNews();
            });
        });

        $artWeekkkey = 'article:home:week';
        $articles['weeks'] = RedisCache::get($artWeekkkey, function() {
            return DbManager::getInstance()->invoke(function ($client){
                $model = Article::invoke($client);
                return $model->getWeeks();
            });
        });

        $artMonthkey = 'article:home:month';
        $articles['months'] = RedisCache::get($artMonthkey, function() {
            return DbManager::getInstance()->invoke(function ($client){
                $model = Article::invoke($client);
                return $model->getMonths();
            });
        });

        $assign += ['links' => $links, 'articles' => $articles];
        return ['template' => 'Home/Theme/Inception/index', 'assign' => $assign];
    }

    /**
     * @description: 分类
     * @param {*}
     * @return {*}
     */
    public function category($param)
    {
        $assign        = $this->getPublic();
        $param['page'] = $param['page'] ?? 1;

        $navchildKey = 'nav:' . $param['id'] . ':child';
        $allnav      = RedisCache::get($navchildKey, function($param) {
            return  DbManager::getInstance()->invoke(function ($client) use ($param) {
                $model = Nav::invoke($client);
                $navs  = $model->getNavAndChildren($param['id']);
                if (!$navs) {
                    throw new Exception('文章分类不存在', 404);
                }
                return $navs;
            });
        }, $param);

        $nav      = end($allnav);
        $nav_ids  = array_column($allnav, 'id');
        $navsKey  = 'nav:' . $param['id'] . ':level';
        $navchild = RedisCache::get($navsKey, function($param) {
            return  DbManager::getInstance()->invoke(function ($client) use ($param) {
                $model = Nav::invoke($client);
                return $model->getNavOrChildren($param['id']);
            });
        }, $param);

        $cateKey = 'nav:' . $param['id'] . ':page:' . $param['page'];
        $datas   = RedisCache::get($cateKey, function($param, $nav_ids) {
            return  DbManager::getInstance()->invoke(function ($client) use ($param, $nav_ids) {
                $limit = 15;
                $model = Article::invoke($client);

                $where              = ['navs_id' => [$nav_ids, 'in']];
                list($list, $total) = $model->getAricles($param['page'], $limit, $where);
                unset($param['id']);
                return Tools::page($param['page'], $list, $total, $limit, $param);
            });
        }, $param, $nav_ids);

        $cateKey = 'nav:' . $param['id'] . ':newArticle';
        $news    = RedisCache::get($cateKey, function($nav_ids) {
            return  DbManager::getInstance()->invoke(function ($client) use ($nav_ids) {
                $model = Article::invoke($client);
                $where = ['navs_id' => [$nav_ids, 'in']];
                return $model->getAricleNews($where);
            });
        }, $nav_ids);

        $assign += [
            'nav' => $nav, 'datas' => $datas, 'news' => $news, 'navchild' => $navchild, 
            'url' => '/category/' . $nav['id'] . '.html'
        ];
        $setting = Tools::getSetting();
        return ['template' => 'Home/Theme/Inception/list', 'assign' => $assign];
    }

    /**
     * @description: 文章详情
     * @param {*}
     * @return {*}
     */
    public function articles($param, $request)
    {
        $assign = $this->getPublic();

        $artKey  = 'article:' . $param['id'];
        $article = RedisCache::get($artKey, function($param) {
            return  DbManager::getInstance()->invoke(function ($client) use ($param) {
                $model   = Article::invoke($client);
                $article = $model->getDetails($param['id']);
                if (!$article) {
                    throw new Exception('文章不存在', 404);
                }
                $article['next']     = $model->getNext($param['id'], $article['navs_id']);
                $article['previous'] = $model->getPrevious($param['id'], $article['navs_id']);
                return $article;
            });
        }, $param);

        $nav_id      = $article['navs_id'];
        $navchildKey = 'nav:' . $nav_id . ':child';
        $allnav      = RedisCache::get($navchildKey, function($nav_id) {
            return  DbManager::getInstance()->invoke(function ($client) use ($nav_id) {
                $model = Nav::invoke($client);
                return $model->getNavAndChildren($nav_id);
            });
        }, $nav_id);

        $navsKey  = 'nav:' . $nav_id . ':level';
        $navchild = RedisCache::get($navsKey, function($nav_id) {
            return  DbManager::getInstance()->invoke(function ($client) use ($nav_id) {
                $model = Nav::invoke($client);
                return $model->getNavOrChildren($nav_id);
            });
        }, $nav_id);

        $nav_ids = array_column($allnav, 'id');
        $cateKey = 'nav:' . $article['navs_id'] . ':newArticle';
        $news    = RedisCache::get($cateKey, function($nav_ids) {
            return  DbManager::getInstance()->invoke(function ($client) use ($nav_ids) {
                $model = Article::invoke($client);
                $where = ['navs_id' => [$nav_ids, 'in']];
                return $model->getAricleNews($where);
            });
        }, $nav_ids);
        $setting = Tools::getSetting();

        $task = TaskManager::getInstance();
        $task->async(new TaskArticleRead([
            'id'      => $article['id'],
            'navs_id' => $article['navs_id'],
            'ip'      => Tools::clientRealIP($request),
        ]));
        $assign += [
            'article' => $article, 'news' => $news, 'navchild' => $navchild, 
            'comment' => $setting['comment'], 'comment_audit' => $setting['comment_audit']
        ];
        $templateName = $article['content_type'] == 0 ? 'article' : 'markdownarticle';
        return ['template' => 'Home/Theme/Inception/' . $templateName, 'assign' => $assign];
    }

    /**
     * @description: 搜索页
     * @param {*}
     * @return {*}
     */
    public function search($param)
    {
        $assign = $this->getPublic();
        if (!$param['search']) {
            return ['redirectUrl' => 'Home/Theme/Inception/index.html'];
        }
        $result = DbManager::getInstance()->invoke(function ($client) use ($param) {
            $page  = $param['page'] ?? 1;
            $limit = 15;
            $where = [];
            $navModel      = Nav::invoke($client);
            $articleModel  = Article::invoke($client);
            $nav_id       = $param['nav_id'] ?: 0;
            if ($nav_id) {
                $navs    = $navModel->getNavAndChildren($param['nav_id']);
                $nav_ids = array_column($navs, 'id');
                $where['navs_id']  = [$nav_ids, 'in'];
            }
            $news               = $articleModel->getAricleNews($where);
            $navchild           = $navModel->getNavOrChildren($nav_id);
            $where['MATCH (name,content,keywords,description) AGAINST (? IN BOOLEAN MODE)'] = [['+'.$param['search']], '?'];
            list($list, $total) = $articleModel->getAricles($page, $limit, $where);
            $datas              = Tools::page($page, $list, $total, $limit, $param);
            return [$datas, $news, $navchild];
        });
        list($datas, $news, $navchild) = $result;
        $assign += [
            'datas' => $datas, 'news' => $news, 'navchild' => $navchild, 
            'param' => $param, 'url' => '/search.html'
        ];
        return ['template' => 'Home/Theme/Inception/search', 'assign' => $assign];
    }

    /**
     * @description: 获取公共部分，分类及友情链接
     * @param {*}
     * @return {*}
     */
    protected function getPublic()
    {
        $key  = 'nav:home';
        $navs = RedisCache::get($key, function() {
            return DbManager::getInstance()->invoke(function ($client) {
                $model = Nav::invoke($client);
                return $model->getHomeNavs();
            });
        });
        $title = Tools::getSetting()['title'];
        return ['navs' => $navs, 'title' => $title];
    }
}
